using Spine.Unity;
using UnityEngine;
using UnityEngine.Events;

namespace Spine.Unity.Examples {
    /// <summary>
    /// 基础平台游戏角色控制器
    /// 实现角色移动、跳跃、动画状态管理和物理交互
    /// </summary>
    [RequireComponent(typeof(CharacterController))]  // 自动添加CharacterController组件
    public class BasicPlatformerController : MonoBehaviour 
    {
        
        #region 角色状态枚举
        public enum CharacterState {
            None,    // 无状态
            Idle,    // 空闲状态
            Walk,    // 行走状态
            Run,     // 奔跑状态
            Crouch,  // 蹲下状态
            Rise,    // 起身状态
            Fall,    // 下落状态
            Attack   // 攻击状态
        }
        #endregion

        #region Inspector 配置区域
        [Header("核心组件")]
        [Tooltip("角色控制器组件")]
        public CharacterController controller;

        [Header("输入设置")]
        [Tooltip("水平移动轴")]
        public string XAxis = "Horizontal";
        
        [Tooltip("垂直移动轴")]
        public string YAxis = "Vertical";
        
        [Tooltip("跳跃按钮")]
        public string JumpButton = "Jump";

        [Header("移动参数")]
        [Tooltip("行走速度")]
        public float walkSpeed = 1.5f;
        
        [Tooltip("奔跑速度")]
        public float runSpeed = 7f;
        
        [Tooltip("重力缩放系数")]
        public float gravityScale = 6.6f;

        [Header("跳跃设置")]
        [Tooltip("跳跃初速度")]
        public float jumpSpeed = 25;
        
        [Tooltip("最小跳跃持续时间")]
        public float minimumJumpDuration = 0.5f;
        
        [Tooltip("跳跃中断系数")]
        public float jumpInterruptFactor = 0.5f;
        
        [Tooltip("强制蹲下速度阈值")]
        public float forceCrouchVelocity = 25;
        
        [Tooltip("强制蹲下持续时间")]
        public float forceCrouchDuration = 0.5f;

        [Header("动画控制")]
        [Tooltip("骨骼动画控制器")]
        public SkeletonAnimationHandleExample animationHandle;
        #endregion

        // 事件系统
        public event UnityAction OnJump;    // 触发跳跃事件
        public event UnityAction OnLand;     // 触发落地事件
        public event UnityAction OnHardLand; // 触发硬着陆事件

        // 状态变量
        Vector2 input = default(Vector2);    // 输入向量
        Vector3 velocity = default(Vector3); // 速度向量
        float minimumJumpEndTime = 0;        // 最小跳跃结束时间
        float forceCrouchEndTime;            // 强制蹲下结束时间
        bool wasGrounded = false;            // 上一帧是否在地面上

        CharacterState previousState, currentState; // 状态缓存

        void Update () {
            float dt = Time.deltaTime;
            bool isGrounded = controller.isGrounded; // 检测地面接触
            bool landed = !wasGrounded && isGrounded; // 落地检测

            // 输入处理
            input.x = Input.GetAxis(XAxis);
            input.y = Input.GetAxis(YAxis);
            bool inputJumpStop = Input.GetButtonUp(JumpButton);
            bool inputJumpStart = Input.GetButtonDown(JumpButton);
            
            // 蹲下状态判断
            bool doCrouch = (isGrounded && input.y < -0.5f) || 
                           (forceCrouchEndTime > Time.time);
            bool doJumpInterrupt = false;
            bool doJump = false;
            bool hardLand = false;

            // 落地时的强制蹲下逻辑
            if (landed) {
                if (-velocity.y > forceCrouchVelocity) {
                    hardLand = true;
                    doCrouch = true;
                    forceCrouchEndTime = Time.time + forceCrouchDuration;
                }
            }

            // 跳跃中断判断
            if (!doCrouch) {
                if (isGrounded) {
                    if (inputJumpStart) doJump = true; // 触发跳跃
                } else {
                    doJumpInterrupt = inputJumpStop && 
                                      Time.time < minimumJumpEndTime;
                }
            }

            // 物理模拟
            Vector3 gravityDeltaVelocity = Physics.gravity * (gravityScale * dt);

            if (doJump) {
                velocity.y = jumpSpeed;          // 设置跳跃初速度
                minimumJumpEndTime = Time.time + minimumJumpDuration;
            } else if (doJumpInterrupt) {
                if (velocity.y > 0)
                    velocity.y *= jumpInterruptFactor; // 跳跃中断时削弱速度
            }

            // 水平移动处理
            velocity.x = 0;
            if (!doCrouch) {
                if (input.x != 0) {
                    velocity.x = Mathf.Abs(input.x) > 0.6f 
                                 ? runSpeed : walkSpeed;
                    velocity.x *= Mathf.Sign(input.x); // 保持方向
                }
            }

            // 重力应用与移动更新
            if (!isGrounded) {
                if (wasGrounded) {
                    if (velocity.y < 0) velocity.y = 0; // 地面碰撞时重置下落速度
                } else {
                    velocity += gravityDeltaVelocity; // 应用重力
                }
            }
            controller.Move(velocity * dt); // 执行角色移动
            wasGrounded = isGrounded;

            // 状态机更新
            if (isGrounded) {
                currentState = doCrouch ? CharacterState.Crouch : 
                                  (input.x == 0 
                                   ? CharacterState.Idle 
                                   : (Mathf.Abs(input.x) > 0.6f 
                                      ? CharacterState.Run 
                                      : CharacterState.Walk));
            } else {
                currentState = velocity.y > 0 
                              ? CharacterState.Rise 
                              : CharacterState.Fall;
            }

            // 状态变更检测
            bool stateChanged = previousState != currentState;
            previousState = currentState;

            // 动画控制
            if (stateChanged) HandleStateChanged();
            if (input.x != 0) animationHandle.SetFlip(input.x);

            // 事件触发
            if (doJump) OnJump.Invoke();
            if (landed) {
                if (hardLand) OnHardLand.Invoke();
                else OnLand.Invoke();
            }
        }

        /// <summary>
        /// 处理角色状态变化时的动画切换
        /// </summary>
        void HandleStateChanged() {
            string stateName = currentState switch {
                CharacterState.Idle   => "idle",
                CharacterState.Walk   => "walk",
                CharacterState.Run    => "run",
                CharacterState.Crouch => "crouch",
                CharacterState.Rise   => "rise",
                CharacterState.Fall   => "fall",
                CharacterState.Attack => "attack",
                _ => string.Empty
            };

            if (!string.IsNullOrEmpty(stateName))
                animationHandle.PlayAnimationForState(stateName, 0);
        }
    }
}